<script setup lang="ts">
import { ref, reactive, onMounted, nextTick, watch, computed } from 'vue'
import { ElScrollbar, ElButton, ElIcon, ElMessage, ElTooltip } from 'element-plus'
import { Delete, Upload, Edit, RefreshRight, CopyDocument } from '@element-plus/icons-vue'
import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'
import DOMPurify from 'dompurify'

// 类型定义
interface Message {
  id: number
  content: string
  isUser: boolean
  timestamp: number
  status?: 'loading' | 'error' | 'success'
  showActions?: boolean
  retryCount?: number
}

// API 配置
const API_CONFIG = {
  baseUrl: 'https://api.deepseek.com',
  apiKey: 'sk-da3569387ef04474a5009f114e84b3e7',
  model: 'deepseek-chat',
  temperature: 0.7,
  maxTokens: 2000,
  maxRetries: 3
}

// 状态管理
const state = reactive({
  messages: [] as Message[],
  inputContent: '',
  loading: false,
  error: null as string | null,
  editingMessageId: null as number | null,
  currentStream: null as ReadableStreamDefaultReader | null
})

// 响应式样式计算
const messageWidth = computed(() => (content: string) => {
  const length = content.length
  return length > 100 ? '80%' : length > 50 ? '70%' : '60%'
})

// Markdown 解析器配置
const md = new MarkdownIt({
  html: false,
  linkify: true,
  highlight: (code, lang) => {
    return hljs.highlightAuto(code).value
  }
})

// 本地存储操作
const STORAGE_KEY = 'chat-history'
function loadHistory() {
  const history = localStorage.getItem(STORAGE_KEY)
  if (history) state.messages = JSON.parse(history)
}
function saveHistory() {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(state.messages))
}
function clearHistory() {
  state.messages = []
  localStorage.removeItem(STORAGE_KEY)
}

// 消息处理
function processContent(content: string) {
  const filtered = content.replace(/[<>]/g, '')
  return DOMPurify.sanitize(md.render(filtered))
}

// 打字机效果处理
const typedContent = ref('')
let typingTimer: number | null = null

function startTypingEffect(targetContent: string, message: Message) {
  let index = 0
  typedContent.value = ''

  function typeCharacter() {
    if (index < targetContent.length) {
      typedContent.value += targetContent.charAt(index)
      message.content = typedContent.value
      index++
      typingTimer = setTimeout(typeCharacter, 50)
    }
  }

  typeCharacter()
}

// AI 响应处理
async function fetchAIResponse(message: string): Promise<Response> {
  if (!API_CONFIG.apiKey) throw new Error('请先配置 API Key')

  const controller = new AbortController()
  const response = await fetch(`${API_CONFIG.baseUrl}/chat/completions`, {
    signal: controller.signal,
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_CONFIG.apiKey}`
    },
    body: JSON.stringify({
      model: API_CONFIG.model,
      messages: [{
        role: 'system',
        content: '你是一个专业的农业专家，请用专业且易懂的语言回答用户的问题。'
      }, {
        role: 'user',
        content: message
      }],
      temperature: API_CONFIG.temperature,
      max_tokens: API_CONFIG.maxTokens,
      stream: true
    })
  })

  if (!response.ok) throw new Error(`API 请求失败: ${response.statusText}`)
  return response
}

// 图片上传处理
async function handleImageUpload(file: File) {
  if (!API_CONFIG.apiKey) {
    ElMessage.error('请先配置 API Key')
    return false
  }

  try {
    const reader = new FileReader()
    const base64 = await new Promise<string>((resolve) => {
      reader.onload = (e) => resolve(e.target?.result as string)
      reader.readAsDataURL(file)
    })

    const imageMessage: Message = {
      id: Date.now(),
      content: `![图片](${base64})`,
      isUser: true,
      timestamp: Date.now(),
      status: 'success'
    }

    state.messages.push(imageMessage)
    saveHistory()
    scrollToBottom()

    return false
  } catch (error) {
    ElMessage.error('图片上传失败')
    return false
  }
}

// 消息操作处理
async function handleRetry(message: Message) {
  if (message.retryCount && message.retryCount >= API_CONFIG.maxRetries) {
    return ElMessage.warning('已达最大重试次数')
  }

  message.status = 'loading'
  message.retryCount = (message.retryCount || 0) + 1
  try {
    const prevContent = message.content
    message.content = ''
    await processMessageStream(message, prevContent)
  } catch (error) {
    message.status = 'error'
    message.content = '请求失败，请重试'
  }
}

async function processMessageStream(message: Message, content: string) {
  const response = await fetchAIResponse(content)
  const reader = response.body?.getReader()
  const decoder = new TextDecoder()
  let rawText = ''
  let done = false

  while (!done && reader) {
    const { value, done: streamDone } = await reader.read()
    done = streamDone
    if (value) {
      const chunk = decoder.decode(value, { stream: true })
      const lines = chunk.split('\n').filter(line => line.trim().startsWith('data:'))
      for (const line of lines) {
        if (line.trim() === 'data: [DONE]') {
          done = true
          break
        }
        try {
          const json = JSON.parse(line.replace('data: ', ''))
          const delta = json.choices?.[0]?.delta?.content
          if (typeof delta === 'string' && delta.length > 0) {
            rawText += delta
            message.content = processContent(rawText)
            // 强制触发响应式
            const idx = state.messages.findIndex(m => m.id === message.id)
            if (idx !== -1) {
              state.messages[idx] = { ...message }
            }
            await nextTick()
            scrollToBottom()
          }
        } catch (error) {
          console.error('解析 JSON 时出错:', error)
        }
      }
    }
  }
  message.content = processContent(rawText)
  message.status = 'success'
  // 流结束后再强制一次
  const idx = state.messages.findIndex(m => m.id === message.id)
  if (idx !== -1) {
    state.messages[idx] = { ...message }
  }
}

async function sendMessage() {
  if (!state.inputContent.trim()) return

  const userMessage: Message = {
    id: Date.now(),
    content: state.inputContent,
    isUser: true,
    timestamp: Date.now(),
    status: 'success'
  }

  state.messages.push(userMessage)
  state.inputContent = ''

  const botMessage: Message = {
    id: Date.now() + 1,
    content: '',
    isUser: false,
    timestamp: Date.now(),
    status: 'loading'
  }

  state.messages.push(botMessage)

  try {
    await processMessageStream(botMessage, userMessage.content)
  } catch (error) {
    botMessage.status = 'error'
    botMessage.content = '请求失败，请重试'
  }
}

// 其他功能
function copyMessage(content: string) {
  navigator.clipboard.writeText(content)
  ElMessage.success('已复制到剪贴板')
}

function editMessage(message: Message) {
  state.editingMessageId = message.id
  state.inputContent = message.content.replace(/!$$.*?$$$.*?$/g, '') // 去除图片标记
}

// 滚动控制
const scrollbarRef = ref<InstanceType<typeof ElScrollbar>>()
function scrollToBottom() {
  nextTick(() => {
    const wrap = scrollbarRef.value?.wrapRef
    if (wrap) {
      scrollbarRef.value?.setScrollTop(wrap.scrollHeight)
    }
  })
}

// 初始化
onMounted(() => {
  loadHistory()
  scrollToBottom()
})

watch(() => state.messages, saveHistory, { deep: true })
</script>

<template>
  <div class="wechat-style-container">
    <el-scrollbar ref="scrollbarRef" class="message-area">
      <div
        v-for="msg in state.messages"
        :key="msg.id"
        class="message-wrapper"
        :class="{ 'user-message-wrapper': msg.isUser }"
        @mouseenter="msg.showActions = true"
        @mouseleave="msg.showActions = false"
      >
        <!-- 头像 -->
        <div class="avatar">
          <template v-if="!msg.isUser">
            <img src="@/assets/img/智链农芯.png" alt="avatar" />
          </template>
          <template v-else>
            <el-avatar :size="40" style="background: #67c23a; color: #fff; font-weight: bold; font-size: 22px;">农</el-avatar>
          </template>
        </div>
        <!-- 消息主体 -->
        <div class="message-content-wrapper">
          <!-- 时间戳 -->
          <div class="timestamp">
            {{ new Date(msg.timestamp).toLocaleString() }}
          </div>
          <!-- 消息内容 -->
          <div
            class="message-bubble"
            :class="{ 'user-bubble': msg.isUser }"
          >
            <div class="content" v-html="msg.content"></div>
            <!-- 加载状态 -->
            <div v-if="msg.status === 'loading'" class="typing-indicator">
              <div class="dot"></div>
              <div class="dot"></div>
              <div class="dot"></div>
            </div>
            <!-- 操作按钮（下方悬浮） -->
            <transition name="fade">
              <div v-if="msg.showActions" class="message-actions-bottom">
                <template v-if="msg.status === 'error'">
                  <div class="action-btn-wrap tooltip-wrap">
                    <el-button
                      :icon="RefreshRight"
                      class="action-btn"
                      @click="handleRetry(msg)"
                    />
                    <span class="action-tooltip">重试</span>
                  </div>
                </template>
                <template v-if="msg.isUser">
                  <div class="action-btn-wrap tooltip-wrap">
                    <el-button
                      :icon="Edit"
                      class="action-btn"
                      @click="editMessage(msg)"
                    />
                    <span class="action-tooltip">编辑</span>
                  </div>
                </template>
                <div class="action-btn-wrap tooltip-wrap">
                  <el-button
                    :icon="CopyDocument"
                    class="action-btn"
                    @click="copyMessage(msg.content)"
                  />
                  <span class="action-tooltip">复制</span>
                </div>
              </div>
            </transition>
          </div>
        </div>
      </div>
    </el-scrollbar>

    <!-- 输入区域 -->
    <div class="input-area">
      <div class="toolbar">
        <el-button :icon="Delete" @click="clearHistory">清空记录</el-button>
        <el-upload
          action="#"
          :show-file-list="false"
          :before-upload="handleImageUpload"
        >
        </el-upload>
      </div>
      <div class="input-wrapper">
        <textarea
          v-model="state.inputContent"
          @keydown.enter.prevent="sendMessage"
          placeholder="输入您的问题... (Enter 发送)"
          class="input-box"
          autofocus
        ></textarea>
        <el-button
          type="primary"
          @click="sendMessage"
          :loading="state.loading"
          class="send-button"
        >
          发送
        </el-button>
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.wechat-style-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: #f0f0f0;

  .message-area {
    flex: 1 1 0%;
    overflow: auto;
    padding: 20px 8%;
    background: #e5e5e5;

    .message-wrapper {
      display: flex;
      margin: 20px 0;
      transition: transform 0.3s ease;
      position: relative;

      &.user-message-wrapper {
        flex-direction: row-reverse;
        .message-content-wrapper {
          align-items: flex-end;
        }
      }

      .avatar {
        width: 40px;
        height: 40px;
        margin: 0 10px;

        img {
          width: 100%;
          height: 100%;
          border-radius: 50%;
          object-fit: cover;
        }
      }

      .message-content-wrapper {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
      }
      .timestamp {
        color: #666;
        font-size: 12px;
        margin-bottom: 4px;
        margin-left: 2px;
      }
      .message-bubble {
        display: inline-block;
        position: relative;
        min-width: 48px;
        max-width: 60vw;
        width: auto;
        padding: 10px 16px;
        border-radius: 8px;
        background: #fff;
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        transition: max-width 0.3s, min-width 0.3s, padding 0.3s;
        font-size: 15px;
        line-height: 1.7;
        vertical-align: top;
        word-break: break-word;
      }
      .user-bubble {
        background: #95ec69;
        border-radius: 8px 0 8px 8px;
      }
      .content {
        color: #222;
        background: transparent;
        font-size: 16px;
        font-family: -apple-system,BlinkMacSystemFont,'PingFang SC','Hiragino Sans GB','Microsoft YaHei',sans-serif;
        font-weight: normal;
        border: none;
        line-height: 1.5;
        word-break: break-word;
        white-space: pre-wrap;
      }
      .typing-indicator {
        display: flex;
        padding: 10px 0;
        .dot {
          width: 8px;
          height: 8px;
          margin: 0 3px;
          background: #ddd;
          border-radius: 50%;
          animation: typing 1.4s infinite ease-in-out;
          &:nth-child(2) { animation-delay: 0.2s }
          &:nth-child(3) { animation-delay: 0.4s }
        }
      }
      .message-actions-bottom {
        display: flex;
        gap: 10px;
        justify-content: flex-end;
        margin-top: 6px;
        position: absolute;
        left: 0;
        right: 0;
        bottom: -38px;
        z-index: 2;
        pointer-events: auto;
      }
      .action-btn-wrap {
        display: flex;
        align-items: center;
        position: relative;
      }
      .tooltip-wrap {
        .action-tooltip {
          position: absolute;
          left: 50%;
          top: -32px;
          transform: translateX(-50%) scale(0.95);
          background: rgba(60,60,60,0.92);
          color: #fff;
          font-size: 12px;
          padding: 3px 12px;
          border-radius: 6px;
          opacity: 0;
          pointer-events: none;
          white-space: nowrap;
          transition: opacity 0.18s, transform 0.18s;
          z-index: 10;
        }
        &:hover .action-tooltip {
          opacity: 1;
          transform: translateX(-50%) scale(1);
        }
      }
      .action-btn {
        background: transparent;
        border-radius: 8px;
        min-width: 32px;
        height: 32px;
        padding: 0;
        font-size: 16px;
        color: #666;
        border: none;
        box-shadow: none;
        transition: all 0.2s;
        z-index: 1;
        &:hover {
          background: #f5f7fa;
          border-radius: 50%;
          color: #409eff;
          box-shadow: 0 2px 8px rgba(64,158,255,0.10);
        }
        .el-icon {
          margin: 0;
        }
      }
    }
  }

  .input-area {
    border-top: 1px solid #d9d9d9;
    padding: 15px;
    background: white;

    .toolbar {
      margin-bottom: 10px;
      display: flex;
      gap: 10px;
    }

    .input-wrapper {
      display: flex;
      gap: 10px;

      .input-box {
        flex: 1;
        height: 80px;
        padding: 12px;
        border: 1px solid #dcdfe6;
        border-radius: 4px;
        resize: none;
        font-size: 14px;
        line-height: 1.5;
        transition: all 0.3s ease;

        &:focus {
          border-color: #409eff;
          box-shadow: 0 0 8px rgba(64, 158, 255, 0.2);
        }
      }

      .send-button {
        height: 80px;
        width: 100px;
      }
    }
  }
}

@keyframes typing {
  0%, 100% { transform: translateY(0) }
  50% { transform: translateY(-5px) }
}

.fade-enter-active, .fade-leave-active {
  transition: opacity 0.2s;
}
.fade-enter-from, .fade-leave-to {
  opacity: 0;
}
</style>

<style lang="scss">
body, html {
  height: 100vh;
  margin: 0;
  padding: 0;
  overflow: hidden;
}
</style>
